/**
 * 中文对象封装 (zh-object.js)
 * 支持 ES6+ Object 所有操作 + 链式调用（返回新对象，不修改原始对象）
 * 含 JSDoc 参数提示 + 常用扩展工具方法
 */

class 对象 {
  /**
   * 构造函数 - 创建对象操作实例
   * @param {Object} [值={}] 初始对象，默认为空对象
   */
  constructor(值 = {}) {
    this._值 = { ...值 };
  }

  /**
   * 获取原始对象的浅拷贝
   * @returns {Object} 对象的浅拷贝
   */
  取值() {
    return { ...this._值 };
  }

  /**
   * 打印当前对象到控制台
   * @returns {对象} 返回this以支持链式调用
   */
  打印() {
    console.log(this._值);
    return this;
  }

  /**
   * 获取对象所有可枚举属性的键名
   * @returns {Array<string>} 键名数组
   */
  取键() {
    return Object.keys(this._值);
  }

  /**
   * 获取对象所有可枚举属性的值
   * @returns {Array<any>} 值数组
   */
  取值列表() {
    return Object.values(this._值);
  }

  /**
   * 获取对象所有可枚举属性的键值对
   * @returns {Array<Array<string, any>>} 键值对数组
   */
  取条目() {
    return Object.entries(this._值);
  }

  /**
   * 获取指定属性的属性描述符
   * @param {string} 键 属性名称
   * @returns {Object|null} 属性描述符对象或null
   */
  取属性描述(键) {
    return Object.getOwnPropertyDescriptor(this._值, 键);
  }

  /**
   * 检查对象是否拥有指定的自有属性
   * @param {string} 键 属性名称
   * @returns {boolean} 是否拥有该属性
   */
  是否自有属性(键) {
    return Object.hasOwn(this._值, 键);
  }

  /**
   * 定义或修改对象的属性
   * @param {string} 键 属性名称
   * @param {Object} 描述 属性描述符对象
   * @returns {对象} 新的对象实例
   */
  定义属性(键, 描述) {
    const 新对象 = { ...this._值 };
    Object.defineProperty(新对象, 键, 描述);
    return new 对象(新对象);
  }

  /**
   * 删除对象的指定属性
   * @param {string} 键 属性名称
   * @returns {对象} 新的对象实例
   */
  删除属性(键) {
    const 新对象 = { ...this._值 };
    delete 新对象[键];
    return new 对象(新对象);
  }

  /**
   * 合并多个对象到当前对象
   * @param {...Object|...对象} 对象列表 要合并的对象列表
   * @returns {对象} 合并后的新对象实例
   */
  合并(...对象列表) {
    const 新对象 = Object.assign({}, this._值, ...对象列表.map(o => o instanceof 对象 ? o._值 : o));
    return new 对象(新对象);
  }

  /**
   * 创建对象的浅拷贝
   * @returns {对象} 新的对象实例
   */
  克隆() {
    return new 对象({ ...this._值 });
  }

  /**
   * 冻结对象，使其不可修改
   * @returns {对象} 新的冻结对象实例
   */
  冻结() {
    return new 对象(Object.freeze({ ...this._值 }));
  }

  /**
   * 密封对象，使其不可添加或删除属性
   * @returns {对象} 新的密封对象实例
   */
  密封() {
    return new 对象(Object.seal({ ...this._值 }));
  }

  /**
   * 判断对象是否可扩展
   * @returns {boolean} 对象是否可扩展
   */
  判断可扩展() {
    return Object.isExtensible(this._值);
  }

  /**
   * 判断对象是否冻结
   * @returns {boolean} 对象是否冻结
   */
  判断冻结() {
    return Object.isFrozen(this._值);
  }

  /**
   * 扩展对象（浅合并）
   * @param {Object|对象} 源对象 要合并的源对象
   * @returns {对象} 扩展后的新对象实例
   */
  扩展(源对象) {
    return this.合并(源对象);
  }

  /**
   * 对对象的每个值应用映射函数
   * @param {Function} 回调 映射函数，接收(value, key, object)参数
   * @returns {对象} 映射后的新对象实例
   */
  映射值(回调) {
    const 新对象 = {};
    for (const [k, v] of Object.entries(this._值)) {
      新对象[k] = 回调(v, k, this._值);
    }
    return new 对象(新对象);
  }

  /**
   * 根据回调函数过滤对象的键
   * @param {Function} 回调 过滤函数，接收(key, value)参数
   * @returns {对象} 过滤后的新对象实例
   */
  过滤键(回调) {
    const 新对象 = {};
    for (const [k, v] of Object.entries(this._值)) {
      if (回调(k, v)) 新对象[k] = v;
    }
    return new 对象(新对象);
  }

  /**
   * 将对象转换为JSON字符串
   * @param {number|string} [缩进=2] 缩进空格数或字符串
   * @returns {string} JSON字符串
   */
  转JSON(缩进 = 2) {
    return JSON.stringify(this._值, null, 缩进);
  }

  /**
   * 将对象转换为字符串表示
   * @returns {string} 对象的字符串表示
   */
  转字符串() {
    return String(this._值);
  }

  /**
   * 创建对象的深拷贝
   * @returns {对象} 深拷贝后的新对象实例
   */
  取深拷贝() {
    return new 对象(JSON.parse(JSON.stringify(this._值)));
  }

  /**
   * 获取对象深层属性值（支持点号路径 a.b.c）
   * @param {string} 路径 属性路径字符串
   * @returns {any} 属性值或undefined
   */
  取路径值(路径) {
    return 路径.split('.').reduce((o, k) => (o ? o[k] : undefined), this._值);
  }

  /**
   * 设置对象深层属性值（支持点号路径 a.b.c）
   * @param {string} 路径 属性路径字符串
   * @param {any} 值 要设置的值
   * @returns {对象} 设置后的新对象实例
   */
  设路径值(路径, 值) {
    const 新对象 = JSON.parse(JSON.stringify(this._值));
    const keys = 路径.split('.');
    let temp = 新对象;
    keys.forEach((k, i) => {
      if (i === keys.length - 1) temp[k] = 值;
      else temp[k] = temp[k] || {};
      temp = temp[k];
    });
    return new 对象(新对象);
  }

  /** 静态方法区 */

  /**
   * 静态方法：判断值是否为对象
   * @static
   * @param {any} v 要判断的值
   * @returns {boolean} 是否为对象
   */
  static 是否对象(v) {
    return v !== null && typeof v === 'object' && !Array.isArray(v);
  }

  /**
   * 静态方法：从键值对数组创建对象
   * @static
   * @param {Array<Array<string, any>>} 条目数组 键值对数组
   * @returns {对象} 新的对象实例
   */
  static 从条目(条目数组) {
    return new 对象(Object.fromEntries(条目数组));
  }

  /**
   * 静态方法：创建具有指定原型的对象
   * @static
   * @param {Object|null} [原型=Object.prototype] 原型对象
   * @returns {对象} 新的对象实例
   */
  static 创建(原型 = Object.prototype) {
    return new 对象(Object.create(原型));
  }

  /**
   * 静态方法：获取对象所有键名
   * @static
   * @param {Object} 对象实例 要获取键的对象
   * @returns {Array<string>} 键名数组
   */
  static 键(对象实例) {
    return Object.keys(对象实例);
  }

  /**
   * 静态方法：获取对象所有值
   * @static
   * @param {Object} 对象实例 要获取值的对象
   * @returns {Array<any>} 值数组
   */
  static 值(对象实例) {
    return Object.values(对象实例);
  }

  /**
   * 静态方法：获取对象所有键值对
   * @static
   * @param {Object} 对象实例 要获取条目的对象
   * @returns {Array<Array<string, any>>} 键值对数组
   */
  static 条目(对象实例) {
    return Object.entries(对象实例);
  }
}



// CommonJS 导出

  module.exports = {
    对象,
    default: 对象
  };
  module.exports.对象 = 对象;



// ES 模块导出
// export { 对象 };
// export default 对象;